home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
- CRAZY JACK'S DATE ROUTINES
- USER'S GUIDE
-
- (c)Copyright 1991 by Crazy Jack
- All Rights Reserved
-
- NOTICE
-
- This is NOT Public Domain software! You don't have to pay for it
- (except for distribution costs) but it IS copyrighted. You may
- not sell or distribute the ZDay and ZDate routines or the various
- header, "include", documentation or example files for any charge
- beyond what is currently customary for "shareware" distribution,
- but you may freely incorporate them into your own software with-
- out further charge or royalties. In other words, use Crazy
- Jack's Date Routines freely, but don't steal.
-
- Crazy Jack's Date Routines may only be distributed as a single
- package containing the following 14 files:
-
- READ.ME Introductory remarks and instructions.
- DATES.DOC The User's Guide (this file).
- DATES.ASM The Date Routines assembler source.
- DATES.LST The assembly listing.
- DATES.OBJ The assembled object module.
- DATES.PAS The Turbo Pascal unit source code.
- DATES.TPU The Turbo Pascal v6.0 compiled unit.
- DATES.INC Additional Turbo Pascal source code.
- DATES.H C header for date routines.
- DATENAMS.C Additional C source code for #including.
- DTP.PAS Turbo Pascal date routines demo source code.
- DTP.EXE Compiled Turbo Pascal date routines demo.
- DTC.C Borland C++ C date routines demo source code.
- DTC.EXE C date routines demo, ready-to-run.
-
- If you wish to make changes, go ahead, BUT:
-
- 1.)
- If you distribute the result, it must be done under the
- rules described in this notice.
- 2.)
- Leave the original copyright notices intact; do not remove
- existing material.
- 3.)
- Add your own copyright notices where appropriate.
- 4.)
- Clearly indicate where you have made changes.
-
- Turbo Pascal, Borland C++ and Paradox are trademarks of Borland
- International.
-
-
- 1
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- This material has no warranties, expressed or implied as to suit-
- ability for any particular task.
-
- Let's face it, gang, even when it's theoretically possible, it's
- usually not practical to test most software exhaustively or to
- prove its perfection. Further, as in the case of this software,
- assumptions are made that are not true for all possible inputs.
- For example, no one knows what kind of calendar may be in use
- 10000 years from now (if any), and Gregorian dates have no mean-
- ing in the period before the Gregorian calendar was adopted. (It
- was adopted at different times in different places!) The number
- of days between two dates always includes weekends and holidays;
- you'll have to determine the number of business days yourself.
- And so-on. Only a fool will use any piece of software without
- testing it for suitability first. Since you're getting these
- routines for distribution charges only, what's your beef? Any-
- way, I've included the source code so you can "fix" anything you
- don't like (at your own risk, of course).
-
- The code was assembled with the Turbo Assembler v2.5 and works as
- I intended with programs written in Borland C++ v1.0 (ANSI C
- mode) and Turbo Pascal v6.0 (so far).
-
- SO WHAT GOOD IS IT?
-
- For periods covered by the Gregorian calendar, these routines can
- be used to determine the day of the week for a given date, to
- convert between Gregorian and Julian dates, to validate Gregorian
- dates (Is 2/29/1900 a valid date? No, by the Gregorian 400-year
- rule that was NOT a leap year!), to determine the number of days
- between two dates, and to find a date some number of days from
- another date.
-
- Since there are 36524 or 36525 years per century, by subtracting
- a base Day Number from the Day Numbers your dates yield, you can
- represent a range of a bit over 179 years in a 16-bit unsigned
- integer (Turbo Pascal "word").
-
- By storing your dates as Day Numbers you simplify the comparison,
- testing and sorting of dates. By using the Day Number as an in-
- dex into a suitably constructed bit table you can determine if a
- day is a special date such as a holiday.
-
- The monotonic nature of the Day Numbers eliminates the need for
- century break testing, something that will soon be a problem.
-
-
-
- 2
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- INSTALLATION
-
- TURBO PASCAL:
-
- If you use TP v6.0, just copy DATES.TPU into your TPU library and
- DATES.INC into the library where you keep frequently used $In-
- clude files. (You DO have such a library, don't you?)
-
- Those of you with other versions will have to compile the TPU for
- your version. Place DATES.OBJ and DATES.PAS into the same subdi-
- rectory on some drive (your RAM disk is a nice place). Make this
- the default drive and subdirectory. Execute your version of TP
- and load DATES.PAS. Set up to compile to disk, then compile.
- Copy the resulting DATES.TPU into your TPU library. Copy
- DATES.INC into your $Includes library, and you're ready to go.
-
- Borland C:
-
- Copy DATES.OBJ into your object library where the linker can find
- it. Copy DATES.H into your header library, and copy DATENAMS.C
- into your #include library.
-
- THE MECHANICS OF USE
-
- TURBO PASCAL:
-
- You'll need a "uses" statement that calls out "Dates" so the
- DATES.TPU will be accessed. If you need the additional routines
- in DATES.INC, you can use either a {$I dates.inc} statement some-
- where before you use the routines. Or copy DATES.INC into your
- source code and remove the routines you don't need, or alter them
- to suit; for example, you might change day and month names to all
- upper case, or change the month and weekday names to another
- language.
-
- Borland C:
-
- Put a #include statement for "dates.h" in the front of each mo-
- dule in which you use date routines. If you are using DOW() or
- MonthName(), remember to #include or copy (and alter to suit
- yourself) DATENAMS.C into one of the modules so the code will get
- compiled somewhere. YDay() is defined as a macro in DATES.H, and
- DATES.OBJ supplies the code for ZDay() and ZDate(). You must put
- an entry for DATES.OBJ in your project file, or in your make
- file's link command or response file, or wherever is needed so it
- will be linked.
-
-
- 3
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- USING ZDAY AND ZDATE
-
- These are the routines for converting Gregorian dates to and from
- Day Numbers. They are called using the PASCAL calling sequence,
- and are FAR calls. All pointers are FAR pointers.
-
- They can be used with both Borland C and Turbo Pascal programs.
- The header file DATES.H defines the interface for Borland C, and
- the unit DATES.TPU defines it (and supplies the code) for Turbo
- Pascal.
-
- The C calling sequences are defined by these prototypes (which
- you will find, with more detail, in DATES.H):
-
- unsigned long int far pascal ZDay( unsigned int Year,
- unsigned int Month, unsigned int Day );
-
- int far pascal ZDate(unsigned long int DayNumber,
- unsigned int far *Year, unsigned int far *Month,
- unsigned int far *Day );
-
- The Turbo Pascal prototypes (found in DATES.PAS and, thus, in
- DATES.TPU) are:
-
- function ZDay(Year, Month, Day : word) : longint;
-
- function ZDate(DayNumber : longint; var Year, Month, Day : word )
- : boolean;
-
- A call to "ZDay" uses 14 bytes of space on the stack; a call to
- "ZDate" eats 26. The routines occupy 354 bytes of code space and
- no data space. For assembly language coders, the contents of the
- AX, BX, CX and DX registers are destroyed; all others are pre-
- served. The condition flags in the flag register are altered.
-
- ZDAY:
-
- ZDay returns a 32-bit unsigned integer representing the Day Num-
- ber calculated from the supplied Gregorian date. Although the
- Pascal call defines it as a longint, you will not have to worry
- about getting a negative number back.
-
- If the resulting Day Number is zero, you have supplied a Gregor-
- ian date that is too early or too far in the future for the
- calculations to be performed correctly with this routine's
- methods.
-
-
- 4
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- The Year, Month and Day parameters are all unsigned 16-bit inte-
- gers, Year must be the FULL YEAR. 1902 must be supplied as
- 1902, not 02. It must be in the range 1 to 25599 or zero will be
- returned. Month and Day must be in the range 0-65535. This
- should not be too restrictive for most purposes.
-
- Note that Day, Month and Year are all UNSIGNED. Negative values
- are unacceptable in these variables. This is also true of the
- any Day Number you give to ZDate! Negative numbers look like
- large positive numbers and will give Wrong Results!
-
- ZDATE:
-
- The same parameters are used with ZDate. Just supply the Day
- Number, and ZDate fills in the Year, Month and Day for you. The
- supplied Day Number should be greater than 121 and less than
- 23920640. For Day Numbers outside this range, ZDate returns a
- Gregorian date of 0-0-0 and a return value of 0 (FALSE in both
- Pascal and C). A good conversion returns 1 (TRUE in both C and
- Pascal).
-
- NOTE: ZDay can convert certain dates into Day Numbers that are
- outside the range that ZDate can convert back. These dates,
- however, involve years that are either zero or very, very large,
- and are well outside the range of dates that we are likely to be
- interested in.
-
- IMPORTANT
-
- To avoid trouble, remember:
-
- 1.)
- All the numeric values are UNSIGNED!
-
- 2.)
- The year MUST be given IN FULL! 7/4/91 means July 4, 091,
- NOT July 4, 1991!
-
- 3.)
- Check the Day Number you get back from "ZDay". If it is
- ZERO, the date you gave it was WAY out of range, and probab-
- ly nonsense!
-
- PARADOX (AND PARADOX ENGINE) USERS
-
- Paradox stores its dates as long integer Day Numbers. Paradox
- Day Numbers are always 427 LESS than ZDay/ZDate Day Numbers.
- Paradox Day Numbers MOD 7 (like "ZDay" Day Numbers MOD 7) return
- the day of the week.
-
-
- 5
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- OKAY, WHAT DO I DO WITH THESE DATE ROUTINES?
-
- The Day Number is related to the Julian Day Number (the number of
- days since some date in the distant past), but is not the same.
- It is valid only for the years since the Gregorian calendar was
- introduced, whenever that was in your area.
-
- You can use the Day Numbers of two dates to find the number of
- days between them.
-
- The remainder resulting when the Day Number is divided by 7 is
- the day of the week, 0 meaning Sunday thru 6 meaning Saturday.
- This conforms with the day-of-the-week number returned by MS-DOS
- and other software.
-
- In files, store the Day Number instead of the date. To conserve
- space you can subtract a base day number and save the difference.
- Careful choice of the base Day Number will let you use a 16-bit
- unsigned integer for holding the difference. The 65536 days that
- 16 bits holds represent more than 179 years. The monotonic na-
- ture of the Day Numbers means you don't need tricks to compare
- the dates or to sort on them, and you don't have to watch out for
- the turn of the century. None of the values represent invalid
- dates, unlike the method used by DOS (and a lot of other soft-
- ware) to store dates in 16 bits!
-
- All dates, valid or not, convert to Day Numbers of some kind.
- All in-range Day Numbers convert to valid Gregorian dates. So if
- you convert a Gregorian date to a Day Number and back, if the
- resulting Gregorian date doesn't match the original, the original
- is invalid.
-
- For example, if you convert 2/29/1900 to a Day Number you get
- 694082. Convert it back and you get 3/1/1900, so 2/29/1900 is
- not a valid date. And that's true. Even though it looks like it
- should be a leap year, it isn't The 400-year Gregorian rule says
- that the leap year is dropped on the century year unless that
- century year can be divided by 400 without a remainder. If we
- convert 2/29/2000 to a Day Number we get 730606, which converts
- back to 2/29/2000, so that IS a valid date.
-
-
-
-
-
-
-
-
- 6
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- Note that the Day Number tends to be what an invalid date "should
- have been". That is, in the Feb 29, 1900 case shown above, it
- gave the Day Number of March 1, 1900. We can take advantage of
- this to find the last day of a month. Begin with the Gregorian
- date. Add 1 to the month (even to December), set the Day to 0,
- convert to a Day Number, then back to Gregorian.
-
- To find the Julian day of the year, just take the difference
- between the Day Number of the desired date and the Day Number of
- January ZERO (so Jan 1 will come out day 1) of the same year. A
- C macro is defined in DATES.H, and a Pascal function is defined
- in DATES.INC, under the name "YDay", to calculate the Julian day
- of the year.
-
- To convert a Julian date to a Gregorian date, give month 1, the
- Julian day of the year, and the year to ZDay, and convert the
- resulting Day Number back to a Gregorian date.
-
- To find the date of next Friday, take the Day Number of today's
- date MOD 7 (today's day of the week). Subtract this from today's
- Day Number, which gives the Day Number of last Sunday. If to-
- day's day of the week is not than 5 (Friday hasn't come yet), add
- 5 to last Sunday's Day Number, otherwise add 12 (tacking on an
- extra week). This gives the Day Number of NEXT Friday, even if
- TODAY is Friday. You can convert the Day Number back to a Gre-
- gorian date, or save the Day Number for testing. Your program
- can thus determine when next Friday has come (or passed) for
- doing Friday Processing, at which time you can calculate the NEXT
- Friday Day Number +to continue the cycle.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 7
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- EXTRAS
-
- DATES.PAS:
-
- This is the source code for DATES.TPU. It uses the universal
- date calculation routines in DATES.OBJ, which have been designed
- to work with both Pascal and C, so programs written in either
- language will produce identical Day Numbers.
-
- DATES.INC:
-
- This is Turbo Pascal code that defines YDay (the Julian day of
- the year function), DOW (a function that returns the day of the
- week spelled out in a string), and MonthName (a function that
- returns the name of the month spelled out in a string).
-
- You can use it as is, just providing a {$I DATES.INC} in your
- code, or you can copy it into your code with your editor and
- remove what you're not using and modify the rest. You might, for
- instance, change the weekday and month names to all caps or ano-
- ther language. DOW and MonthName protect themselves by masking
- the month or day of the week to small ranges (to keep them from
- going outside their tables). You can change this to modular
- division or range checking if you so desire; you've got the
- source code.
-
- Note that the strings returned by DOW and MonthName are specially
- typed instead of being generic STRINGs. Generic STRINGs eat 255
- bytes apiece somewhere in storage in temporary space provided by
- Turbo Pascal; there's no sense in wasting all that space.
-
- DATES.H:
-
- This header file provides the ZDay() and ZDate() prototypes for
- ANSI C users. It also has prototypes for YDay(), DOW() and
- MonthName(), and it defines YDay() as a macro. The actual code
- for DOW() and MonthName() are in DATENAMS.C.
-
- DATENAMS.C:
-
- This is a file to be #included, or copied into and modified, in
- one of the modules of your C program to provide the functions
- DOW() and MonthName() defined in DATES.H. If you don't use 'em,
- you don't include 'em. Since there are no NEAR or FAR modifiers
- in any of the declarations, they compile to YOUR memory model.
-
-
-
- 8
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- THE DEMOS
-
- Demo programs are provided in both C (DTC) and Turbo Pascal (DTP)
- to illustrate some of the ways in which the date routines can be
- used. They are also handy for doing manual date calculations.
-
- Both demo programs work the same way. Execute either from the
- command line (no parameters are used) and it will ask "Gimme a
- date: ".
-
- You can type in a single Day Number, a Julian date (ddd/yyyy), or
- a Gregorian date (mm/dd/yyyy), then hit ENTER.
-
- IMPORTANT--> All digits of the year must be given; if you mean
- 1991, you must specify "1991", NOT "91".
-
- The program will then show you various conversion results and
- return to the "Gimme a date: " prompt.
-
- To exit, just hit ENTER from the prompt.
-
- I have included the source code for both to serve as usage exam-
- ples.
-
- If you compile the C version you'll get some warnings, all of
- which are meaningless. For some reason, Borland's C compilers
- don't know that a "do" can ALWAYS be reached from its "while"!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 9
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- TECHNICAL STUFF
-
- There are a number of descriptions of Day Number routines float-
- ing around. The one I use came from a routine I saw for the HP-
- 65 programmable pocket calculator to find the Julian Day Number.
- To it I added the adjustments for the 400-day Gregorian rule.
- For the coming turn of the century we don't need it since the
- year 2000 divides by 400 without a remainder and is, thus, a leap
- year; but programmers can be picky about details, so -- what the
- heck!
-
- So far, I have written this routine in HP-65, COBOL, Easytrieve,
- BASIC and Pascal. Those implementations are all slow and ineffi-
- cient. Since I now need a date routine at work that I can use
- with assembler, Pascal and C on our PC-type machines I figure I
- may as well do a nice small one in assembler for the 80x86 and be
- done with it.
-
- To calculate the Day Number from a Gregorian date we first adjust
- the year and month so the month values run from 4 to 15, with
- March being 4 and February being 15:
-
- if Month < 3
- then
- Add 13 to Month
- Subtract 1 from Year
- otherwise
- Add 1 to Month.
-
- Now comes the meat of the calculation:
-
- Day Number = Day of the month
- + The Integer Part of (Month * 30.6001)
- + The Integer Part of (Year * 365.25)
- - The Integer Part of (3/4 of
- The Integer Part of (Year / 400)
- ).
-
- (That last mess accounts for the Gregorian 400-year rule.) Now
- if we divide this by 7 (to find the day of the week) we get 0 for
- Saturday. For a variety of reasons, mostly related to common
- practice, I decided to adjust this further by subtracting 1 from
- it so Sunday becomes 0.
-
- If you want to duplicate Paradox Day Numbers, you can change the
- code in ZDAY to subtract 428 instaed of 1, and you'll have to add
-
-
- 10
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- a check for a possible borrow in case of underflow to a not-
- allowed negative value, You'll also have to modify ZDATE to get
- the 428 added back.
-
- Converting back to a Gregorian date is not so easy.
-
- First we back out the Gregorian 400-year rule:
-
- Divide Day Number less 121 by 146097:
- Q = the quotient
- R = the remainder.
-
- if R is not 0
- then
- Add the quotient from ( (R -1) / 36524 ) to Q.
-
- N = Day Number plus 1 plus Q.
-
- Note that 145097 is the number of days in 400 years with the 400-
- year rule applied, and 36524 is the number of days in a century
- in which the century year is NOT a leap year. 36525 is the
- number of days in a century where the century year IS a leap
- year. Once the 400-year rule is backed out, we have ALL centur-
- ies containing 36525 days, which simplifies the remaining calcu-
- lations.
-
- We extract the Gregorian date from the adjusted Day Number "N".
- First we get the tentative year:
-
- Year = The Integer Part of ( (N - 122.1) / 365.25 ).
-
- --and we remove the tentative year's worth of days from the ad-
- justed Day Number "N":
-
- N = N - the Integer Part of (Year * 365.25).
-
- From this we extract the tentative month:
-
- Month = The Integer Part of (N / 30.6001).
-
- The current day is what is left over when we remove the days due
- to the months:
-
- Day = N - The Integer Part of (Month * 30.6001).
-
-
-
-
- 11
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- Finally we adjust the Year and the Month:
-
- if Month > 13
- then
- Subtract 13 from Month
- Add 1 to the Year
- otherwise
- Subtract 1 from the Month.
-
- --and the deed is done.
-
- Since I intend that this set of routines be usable on all PC
- compatible systems, I can't assume the availability of a numeric
- coprocessor or 32-bit arithmetic. So everything is done in 16-bit
- integer arithmetic using the CPU registers (no coprocessor or
- extended registers) and 8086 instructions only. In some places
- it makes the code a little awkward, but it gives its best perfor-
- mance on the lowliest of PCs where it's needed the most.
-
- In a couple of places I had to divide by a number more than 16
- bits long, once in ZDAY, when I had to divide by 146097, and once
- in ZDATE where I had to divide by 306001, Fortunately, both of
- these numbers can be factored into values that fit 16 bits.
-
- Let the division be: A / (B * C), where B and C are the factors
- of the original divisor. We are looking for the quotient Q and
- the remainder R.
-
- Divide A by B:
- Q1 = the quotient
- R1 = the remainder;
-
- Divide Q1 by C:
- Q2 = the quotient
- R2 = the remainder;
-
- ---then:
- the quotient Q = Q2
- the remainder R = R1 + (B * R2).
-
- Divide by the largest factor first to allow the largest dividend.
-
- For those of you who haven't messed around with integer multiply
- and divide as machines generally perform them, they are done the
- way the old mechanical desk calculators did it: by repeated adds
- (multiplication) or subtracts (division) and shifts.
-
-
- 12
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- In division, the dividend is always two units (words or bytes)
- long, and the divisor, quotient and remainder are all one unit
- long. To avoid divide overflow, the value in the high-order
- (leftmost) unit of the dividend must be less than the divisor.
- You will see a number of tests for this in the code.
-
- Likewise, the result of multiplying two single unit numbers is a
- double unit number. Multiplying two 16-bit numbers returns a 32-
- bit product. There is no possibility of overflow.
-
- I take advantage of these built-in "type conversions" wherever
- possible. I also utilize the ability to get both the quotient
- and the remainder from a single divide, something that few high-
- level languages (outside of COBOL) support.
-
- I chose the Pascal calling sequence and use no calls to run-time
- library routines so I can use the same code (DATES.OBJ) with both
- C and Pascal programs.
-
- If you don't mind shoving stuff on the stack and the other fool-
- ing around required, you can use the routines with assembly code
- as well.
-
- To call ZDAY, push, in this order: the 16-bit unsigned integers
- specifying the year, the month and the day onto the stack, then
- execute a FAR CALL to ZDAY. The resulting Day Number is returned
- in the DX:AX register pair.
-
- To call ZDATE, push, in this order: a 32-bit word holding the Day
- Number to be converted (in the usual byte-reversed order), and
- FAR POINTERs to the three 16-bit words to receive the year, the
- month and the day. Then make a FAR CALL to ZDATE. Upon return,
- the Gregorian date will be in the year, month and day words
- pointed to by those addresses you pushed on the stack, and the AX
- register will contain 1 if everything went okay, or zero if the
- Day Number was out of range (testing anything but the AL would be
- wasteful).
-
- Specifying the LARGE model to the assembler and explicitly defin-
- ing all the calls and pointers as PASCAL FAR in "dates.h" allows
- the proper calls and pointers to be compiled and proper linking
- to occur with all the C memory models. For example, the program
- DTC.EXE was compiled as a TINY model program and works just fine.
-
-
-
-
-
- 13
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- PERFORMANCE
-
- There would be no sense in going to all this trouble if the
- resulting code was neither smaller nor faster than code produced
- by a good compiler. There may be no sense in it anyway, but it
- was fun.
-
- Is there an improvement?
-
- 354 bytes is not a lot of space to take up, and stack use is held
- down, but this is no big deal.
-
- The most convenient alternative routines I can find for a speed
- comparison is the set of date "encode" and "decode" routines
- found in the Borland Paradox Engine. I don't mean any offense to
- Borland with this test, it's just what I have at hand. I presume
- their routines are coded in C using double precision arithmetic.
- The results would be more general-purpose and portable, but less
- efficient.
-
- In my routines I don't need general-purpose methods. I have been
- able to factor into 16-bit values the numbers that I need to
- divide by, so I can use integer multiplies and divides. The
- performance differences on different processors are interesting.
-
- I concocted a test program (in Turbo Pascal, if you must know)
- that allows me to enter a loop count. It then runs a counted
- series of Day Numbers (starting in the current century) first
- through the conversion to Gregorian date, then back to the Day
- Number, using the Paradox Engine routines. The program pauses
- before starting, then again at the end so I can run my stopwatch.
- The same series of Day Numbers is processed again through
- ZDate/ZDay. Compared to the calculation time, the loop and cal-
- ling sequences are not too important.
-
- No, I didn't use precision timing: I'm not interested in minute
- improvements.
-
- The first system I tried it on was an old IBM XT running at 4.77
- mHz with an 8088 processor. It took around 55 seconds for the
- Paradox Engine routines to get through 5,000 iterations of the
- loop.
-
- It took ZDate/ZDay about 5 seconds to do the job.
-
-
-
-
- 14
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- I then moved to an IBM AT running at 8 mHz. Here I set the loop
- count to 20,000. The PXEngine routines took about a minute, and
- ZDate/Zday around 4 seconds.
-
- On a 15 mHz 80386 system the times were about the same as the AT
- when the loop count was set to 40,000.
-
- The machine I use at home is an 8 mHz XT clone with an NEC V20 in
- place of the 8088, with the RAM refresh rate reduced somewhat.
- Central Point Software's PCSHELL says it runs at around 195% of a
- PC. It took 58 second time to do 10,000 iterations of the Para-
- dox Engine loop. The microcoding improvements of the multiply
- and divide instructions in the V20 show up in the Zdate/ZDay
- loop: 2 seconds.
-
- So was it worth it? I doubt that the performance improvement
- will save enough time over the years to cover the time and cost
- of writing it, let alone the additional cost (in MY time) of
- doing this writeup. Calculating dates is not, after all, a large
- part of any program. But it was fun, and the routine IS small
- and fast, and I have lots of uses for it. I'm satisfied.
-
-
- MODIFICATIONS
-
- Those of you who are into this sort of thing and don't care about
- the Gregorian 400-day rule (okay for the coming turn of the cen-
- tury) may wish to reduce the size and increase the speed of these
- routines by removing the 400-day rule code. Just remember to
- watch the register contents. I went to some trouble to try to
- have things wind up in registers where I wanted them, and pulling
- code may not leave things the way the other code expects them to
- be. If you make changes, you're on your own.
-
-
- OTHER COMPILERS AND C++
-
- While I haven't bothered to try it, I presume that ZDay and ZDate
- will work correctly with Borland C++ (C++ mode) since the use of
- the Pascal calling sequence avoids name mangling problems.
-
- For use with other C compilers you may have to alter the segment
- and/or group names. The use of the Pascal calling sequence amy
- create problems with other C compilers. I don't use other com-
- pilers, so I don't know. Since you have the source code, you can
- play around with it if you need to.
-
-
- 15
-
- CRAZY JACK'S DATE ROUTINES USER'S GUIDE
-
-
- GETTING IN TOUCH
-
- Everything you need should be right here in this package, but if
- you feel the need to make comments about these routines, or to
- ask questions, you can drop me a line at:
-
- ATTN: Crazy Jack
- The Northern Illinois Klugewerks
- P.O. Box 7284
- Buffalo Grove, IL 60089
-
- If you expect a reply, you MUST enclose a stamped, self-addressed
- envelope. I will try to answer, but, like most of you, I have a
- "day" job that eats the bulk of my time, including evenings and
- parts of weekends.
-
- If you have improvements to the code, please send them along.
- But remember, the code must be optimized for the 8088, not the
- bigger, faster chips. Also, if you think you've found a mistake
- in my code, look carefully. I may have taken advantage of side
- effects that let me skip tests or use byte instead of word oper-
- ations. In other cases I have taken extra code space to reduce
- the amount of pipeline dumping due to jumps.
-
- Alterations which reduce the size of the code and/or increase its
- speed (without sacrificing function) are especially welcome. In
- particular, I'd like a cleaner method for backing out the 400-
- year Gregorian rule. No, removing it altogether does NOT quali-
- fy!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 16
-
-
- ----------------end-of-author's-documentation---------------
-
- Software Library Information:
-
- This disk copy provided as a service of
-
- Public (software) Library
-
- We are not the authors of this program, nor are we associated
- with the author in any way other than as a distributor of the
- program in accordance with the author's terms of distribution.
-
- Please direct shareware payments and specific questions about
- this program to the author of the program, whose name appears
- elsewhere in this documentation. If you have trouble getting
- in touch with the author, we will do whatever we can to help
- you with your questions. All programs have been tested and do
- run. To report problems, please use the form that is in the
- file PROBLEM.DOC on many of our disks or in other written for-
- mat with screen printouts, if possible. PsL cannot debug pro-
- programs over the telephone, though we can answer questions.
-
- Disks in the PsL are updated monthly, so if you did not get
- this disk directly from the PsL, you should be aware that the
- files in this set may no longer be the current versions. Also,
- if you got this disk from another vendor and are having prob-
- lems, be aware that some files may have become corrupted or
- lost by that vendor. Get a current, working disk from PsL.
-
- For a copy of the latest monthly software library newsletter
- and a list of the 3,000+ disks in the library, call or write
-
- Public (software) Library
- P.O.Box 35705 - F
- Houston, TX 77235-5705
-
- 1-800-2424-PSL
- MC/Visa/AmEx/Discover
-
- Outside of U.S. or in Texas
- or for general information,
- Call 1-713-524-6394
-
- PsL also has an outstanding
- catalog for the Macintosh.
-